home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1990, 1992, 1993 Aladdin Enterprises. All rights reserved.
-
- This file is part of AFPL Ghostscript.
-
- AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author or
- distributor accepts any responsibility for the consequences of using it, or
- for whether it serves any particular purpose or works at all, unless he or
- she says so in writing. Refer to the Aladdin Free Public License (the
- "License") for full details.
-
- Every copy of AFPL Ghostscript must include a copy of the License, normally
- in a plain ASCII text file named PUBLIC. The License grants you the right
- to copy, modify and redistribute AFPL Ghostscript, but only under certain
- conditions described in the License. Among other things, the License
- requires that the copyright notice and this notice be preserved on all
- copies.
- */
-
- /*$Id: gdevsj48.c,v 1.2 2000/09/19 19:00:22 lpd Exp $*/
- /*
- * StarJet SJ48 printer driver.
- *
- * --- derived from gdevbj10.c 1993-10-07
- * by Mats kerblom (f86ma@dd.chalmers.se).
- */
-
- #include "gdevprn.h"
-
-
- /*
- * The only available resolutions (in the program) are (180,360)x(180,360).
- *
- * Used control codes:
- * <Esc>@ Printer reset
- * <Esc>J<n> Make a n/180 inch linefeed
- * <Esc>\<a><b> Move the print position (a+256b)/180 inch to the right
- * <Esc>*<m><a><b>... Print graphics; m=39: 180*180 dpi
- * m=40: 360*180 dpi
- * m=71: 180*360 dpi
- * m=72: 360*360 dpi
- * a+256b columns is printed.
- */
-
- /* The device descriptor */
- private dev_proc_print_page(sj48_print_page);
- gx_device_printer far_data gs_sj48_device =
- prn_device(prn_std_procs, "sj48",
- 80, /* width_10ths, 8" */
- 105, /* height_10ths, 10.5" */
- 360, /* x_dpi */
- 360, /* y_dpi */
- 0,0,0,0, /* margins */
- 1, sj48_print_page);
-
-
- /* This comes from the bj10/bj200 source. I don't know how it applies
- * for a StarJet. --- Mats kerblom.
- *
- *
- * The following is taken from the BJ200 Programmer's manual. The top
- * margin is 3mm (0.12"), and the bottom margin is 6.4mm (0.25"). The
- * left and right margin depend on the type of paper -- US letter or
- * A4 -- but ultimately rest on a print width of 203.2mm (8"). For letter
- * paper, the left margin (and hence the right) is 6.4mm (0.25"), while
- * for A4 paper, both are 3.4mm (0.13").
- *
- * The bottom margin requires a bit of care. The image is printed
- * as strips, each about 3.4mm wide. We can only attain the bottom
- * margin if the final strip coincides with it. Note that each strip
- * is generated using only 48 of the available 64 jets, and the absence
- * of those bottom 16 jets makes our bottom margin, in effect, about
- * 1.1mm (0.04") larger.
- *
- * The bj200 behaves, in effect, as though the origin were at the first
- * printable position, rather than the top left corner of the page, so
- * we add a translation to the initial matrix to compensate for this.
- *
- * Except for the details of getting the margins correct, the bj200 is
- * no different from the bj10e, and uses the same routine to print each
- * page.
- *
- */
-
-
- /* Send the page to the printer. */
- private int
- sj48_print_page(gx_device_printer *pdev, FILE *prn_stream)
- { int line_size = gx_device_raster((gx_device *)pdev, 0);
- int xres = pdev->x_pixels_per_inch;
- int yres = pdev->y_pixels_per_inch;
- int mode = (yres == 180 ?
- (xres == 180 ? 39 : 40) :
- (xres == 180 ? 71 : 72));
- int bytes_per_column = (yres == 180) ? 3 : 6;
- int bits_per_column = bytes_per_column * 8;
- int skip_unit = bytes_per_column * (xres == 180 ? 1 : 2); /* Skips in step of 1/180" */
- byte *in = (byte *)gs_malloc(8, line_size, "sj48_print_page(in)");
- byte *out = (byte *)gs_malloc(bits_per_column, line_size, "sj48_print_page(out)");
- int lnum = 0;
- int skip = 0;
- int skips;
- int code = 0;
- int last_row = dev_print_scan_lines(pdev);
- int limit = last_row - bits_per_column;
-
- if ( in == 0 || out == 0 )
- { code = gs_error_VMerror;
- gs_note_error(code);
- goto fin;
- }
-
- /* Abort if the requested resolution is unsupported. */
- if ((xres !=180 && xres != 360) || (yres !=180 && yres != 360))
- { code = gs_error_rangecheck;
- gs_note_error(code);
- goto fin;
- }
-
- /* Initialize the printer. */
- fwrite("\033@\000\000", 1, 4, prn_stream); /* <Printer reset>, <0>, <0>. */
-
- /* Transfer pixels to printer. The last row we can print is defined
- by "last_row". Only the bottom of the print head can print at the
- bottom margin, and so we align the final printing pass. The print
- head is kept from moving below "limit", which is exactly one pass
- above the bottom margin. Once it reaches this limit, we make our
- final printing pass of a full "bits_per_column" rows. */
- while ( lnum < last_row )
- {
- byte *in_data;
- byte *in_end = in + line_size;
- byte *out_beg = out;
- byte *out_end = out + bytes_per_column * pdev->width;
- byte *outl = out;
- int count, bnum;
-
- /* Copy 1 scan line and test for all zero. */
- code = gdev_prn_get_bits(pdev, lnum, in, &in_data);
- if ( code < 0 ) goto xit;
- /* The mem... or str... functions should be faster than */
- /* the following code, but all systems seem to implement */
- /* them so badly that this code is faster. */
- { register const long *zip = (const long *)in_data;
- register int zcnt = line_size;
- register const byte *zipb;
- for ( ; zcnt >= 4 * sizeof(long); zip += 4, zcnt -= 4 * sizeof(long) )
- { if ( zip[0] | zip[1] | zip[2] | zip[3] )
- goto notz;
- }
- zipb = (const byte *)zip;
- while ( --zcnt >= 0 )
- {
- if ( *zipb++ )
- goto notz;
- }
- /* Line is all zero, skip */
- lnum++;
- skip++;
- continue;
- notz: ;
- }
-
- /* Vertical tab to the appropriate position. Note here that
- we make sure we don't move below limit. */
- if ( lnum > limit )
- { skip -= (limit - lnum);
- lnum = limit;
- }
-
- /* The SJ48 can only skip in steps of 1/180" */
- if (yres == 180) {
- skips = skip;
- } else {
- if (skip & 1) {
- skip--; /* Makes skip even. */
- lnum--;
- }
- skips = skip/2;
- }
-
- while ( skips > 255 )
- { fputs("\033J\377", prn_stream);
- skips -= 255;
- }
- if ( skips )
- fprintf(prn_stream, "\033J%c", skips);
-
- /* If we've printed as far as "limit", then reset "limit"
- to "last_row" for the final printing pass. */
- if ( lnum == limit )
- limit = last_row;
- skip = 0;
-
- /* Transpose in blocks of 8 scan lines. */
- for ( bnum = 0; bnum < bits_per_column; bnum += 8 )
- { int lcnt = min(8, limit - lnum);
- byte *inp = in;
- byte *outp = outl;
- lcnt = gdev_prn_copy_scan_lines(pdev,
- lnum, in, lcnt * line_size);
- if ( lcnt < 0 )
- { code = lcnt;
- goto xit;
- }
- if ( lcnt < 8 )
- memset(in + lcnt * line_size, 0,
- (8 - lcnt) * line_size);
- for ( ; inp < in_end; inp++, outp += bits_per_column )
- { gdev_prn_transpose_8x8(inp, line_size,
- outp, bytes_per_column);
- }
- outl++;
- lnum += lcnt;
- skip += lcnt;
- }
-
- /* Send the bits to the printer. We alternate horizontal
- skips with the data. The horizontal skips are in units
- of 1/180 inches, so we look at the data in groups of
- 1 or 2 columns depending on resolution (controlled
- by skip_unit). */
- outl = out;
- do
- { int count;
- int n;
- byte *out_ptr;
-
- /* First look for blank groups of columns. */
- while(outl < out_end)
- { n = count = min(out_end - outl, skip_unit);
- out_ptr = outl;
- while ( --count >= 0 )
- { if ( *out_ptr++ )
- break;
- }
- if ( count >= 0 )
- break;
- else
- outl = out_ptr;
- }
- if (outl >= out_end)
- break;
- if (outl > out_beg)
- { count = (outl - out_beg) / skip_unit;
- fprintf(prn_stream, "\033\\%c%c",
- count & 0xff, count >> 8);
- }
-
- /* Next look for non-blank groups of columns. */
- out_beg = outl;
- outl += n;
- while(outl < out_end)
- { n = count = min(out_end - outl, skip_unit);
- out_ptr = outl;
- while ( --count >= 0 )
- { if ( *out_ptr++ )
- break;
- }
- if ( count < 0 )
- break;
- else
- outl += n;
- }
- count = outl - out_beg;
- {
- /* What to transmit is the number of columns in the row.
- Compare this with the <Esc>|*-command wich expects the
- total number of bytes in the graphic row! */
- int count1 = count/bytes_per_column;
- fprintf(prn_stream, "\033*%c%c%c",
- mode, count1 & 0xff, count1 >> 8);
- }
- fwrite(out_beg, 1, count, prn_stream);
- out_beg = outl;
- outl += n;
- }
- while ( out_beg < out_end );
-
- fputc('\r', prn_stream);
- skip = bits_per_column; /* <CR> only moves to the beginning of the row. */
- }
-
- /* Eject the page */
- xit: fputc(014, prn_stream); /* form feed */
- fflush(prn_stream);
- fin: if ( out != 0 )
- gs_free((char *)out, bits_per_column, line_size,
- "sj48_print_page(out)");
- if ( in != 0 )
- gs_free((char *)in, 8, line_size, "sj48_print_page(in)");
- return code;
- }
-